import tweepy
from optparse import OptionParser
import sys
from urllib import urlencode
from numpy import *
from numpy import matrix
from numpy import linalg
import re
import locale
import json
import time
import pdb
import fileinput
import os
import threading

class fitHRG(threading.Thread):
        def __init__(self, infile):
			self.infile = infile
			threading.Thread.__init__(self)   

        def run(self):
			os.system("timeout 500 /Users/ocastaneda/Documents/TU_Delft/2010/IN5000/Tools/fitHRG_GPL/fitHRG -f %s" %self.infile)		

class predictHRG(threading.Thread):
	def __init__(self, infile, outfile):
		self.infile = infile
		self.outfile = outfile
		threading.Thread.__init__(self)

	def run(self):
		os.system("/Users/ocastaneda/Documents/TU_Delft/2010/IN5000/Tools/predictHRG_GPL/predictHRG -f %s" %self.infile + " -n 100 -s %s" %self.outfile)

class ImplicitFollowers2Network:
	def __init__(self, inputfilepath, outputfilepath, screen_name):		
		self.inputfile = inputfilepath
		self.outputfile = outputfilepath
		self.root_screen_name = screen_name
		
		# Account 0 (Imp22Fol)
		#Authentication tokens for Twitter, authenticate, and check rate limit status
		self.auth0 = tweepy.OAuthHandler("i6vYqkDgmUZx2SGBnguzg", "VhFKWet5p6JmWKX89fITvDpl0praa0TO8V7ba0QSl5U")
		self.auth0.set_access_token("335838961-tYqkaP65QyYHiHb5cE1CGV6zB7SIpIQArMqybs", "eHK9NyCX3TtuvKJBKVs3DIKr2EMfh3x508Z3UT56EJE")
		self.api0 = tweepy.API(self.auth0)
		self.my_rate_limit_status0 = self.api0.rate_limit_status()

		# Account 1 (Conv2Fol)
		# Authentication tokens for Twitter, authenticate, and check rate limit status
		self.auth1 = tweepy.OAuthHandler("uEaf4MBF9pu6ePTJT0T3w", "uTwMUJGo6dqciEJ1vVrCJ3wgHrSYR9Vysz2TJ01GLyA")
		self.auth1.set_access_token("335841614-072kBBbxiWHcezvN3Eo9VmMzFnGbehUrqWMXp0Tu", "03jqfVjGPXe219hJHNFBlkKK96igdsvyoFiitnuoJ8")
		self.api1 = tweepy.API(self.auth1)
		self.my_rate_limit_status1 = self.api1.rate_limit_status()
		
		# Account 2 (Int2Fol)
		# Authentication tokens for Twitter, authenticate, and check rate limit status
		self.auth2 = tweepy.OAuthHandler("P07XwnJHUN3dqQxG4zUpw", "fJVg6q79jdtaPNvh2tc1ipv8x9lEiTcwzRf3C24nFQ")
		self.auth2.set_access_token("335844930-HmUJwXcIYbyhvFZE0xCuOZbAIvWjR2gEGV83AxsK", "MTJ2GOv02777TreJkawARTr2YQSMb3UoEjPPCefnGPA")
		self.api2 = tweepy.API(self.auth2)
		self.my_rate_limit_status2 = self.api2.rate_limit_status()

		# Account 3 (Con2Fol)
		# Authentication tokens for Twitter, authenticate, and check rate limit status
		self.auth3 = tweepy.OAuthHandler("FGlMRu1UBRD0K2a0BYBj1w", "ra1uQ6RXpupAzDotakWchgaCrKG5nSlmcST6J5XTl6c")
		self.auth3.set_access_token("335853926-wUuKeH3I4z46LlTVIZ06vyAt3NXSRuINQJj3sYuJ", "qW93vOnz7E7Tq1pMItsEt8bPt2oH04A2WukDP3FplU")
		self.api3 = tweepy.API(self.auth3)
		self.my_rate_limit_status3 = self.api3.rate_limit_status()

		self.account_number = 0
		
		# Initialize Twitter (multiple accounts) and Backtype API calls
		self.api_calls = {0:0, 1:0, 2:0, 3:0}
		self.backtype_api_calls = 0
		
		self.Process()	

	def GetUserID(self, screen_name):		
		# Keep track of the Twitter API Calls
		self.api_calls[self.account_number] = self.api_calls[self.account_number] + 1
		print "Api calls for account %s :" %self.account_number + " [%s] " %self.api_calls[self.account_number] + " (from GetUserTimeline)"
		if (self.api_calls[self.account_number] > 325):
			# Using division modulo 4 so that account numbers rotate
			# every 4 runs of changes in account number.
			self.account_number = (self.account_number + 1) % 4
			print "Sleeping for 10 minutes..."
			time.sleep(60*10)
			self.api_calls[self.account_number] = 0

		user_timeline = None

		try:
			if (self.account_number == 0):
				user_id = self.api0.get_user(screen_name).id
			elif (self.account_number == 1):
				user_id = self.api1.get_user(screen_name).id
			elif (self.account_number == 2): 
				user_id = self.api2.get_user(screen_name).id
			elif (self.account_number == 3):
				user_id = self.api3.get_user(screen_name).id
		except:
			self.output_logs.write("Problem getting user id for user %s" %screen_name)
			pass

		return user_id	
			
	def Process(self):	
		
		outputfilename = self.outputfile
		fqn_filename = outputfilename.split('.')
		
		inputf = open(self.inputfile, 'r')
		inputf2 = open(self.inputfile, 'r')
		outputf = open(self.outputfile, 'w')
		outputf2 = open(fqn_filename[0] + ".predicted", 'w')		

		items = []
		users = []
		items_p = []
		users_p = []
		predicted_followers = []
		
		user_id = self.GetUserID(self.root_screen_name)	
				
		# Read input file (from IFN) to get all users and items added into their 
		# respective lists
		for line in inputf:			
			readline = line.split(',')
			if (users.count(int(readline[0])) == 0):					
				users.append(int(readline[0]))
				print "User: %s" %readline[0]
			if (items.count(int(readline[1])) == 0):
				items.append(int(readline[1]))
				print "Item: %s" %readline[1]
			
		print "Users: " + "%s" %len(users)
		print "Items: " + "%s" %len(items)
		
		# Create a matrix using the length of the users and items list as dimensions
		a = len(users)
		b = len(items)
		mat = array([[0]*a]*b)
		
		# Read input file again and fill in matrix with userXitem relations
		for relation in inputf2:
			refline = relation.split(',')				
			print "Now trying for User: %s" %refline[0]
			print " and Item: %s" %refline[1]
			mat[items.index(int(refline[1]))][users.index(int(refline[0]))] = 1
			print "Matrix now has value 1 in row: " + "%s" %users.index(int(refline[0])) + " and column: " + "%s" %items.index(int(refline[1]))

		# Now create a user-user matrix with dimensions the length of the users list
		user2user = array([[0]*len(users)]*len(users))
		
		# Go through all the users and items in matrix mat and if a relation is found
		# (ie. there is a 1 in that rowXcolumn) then try to connect that user with
		# another user who is also connected with the same item. 
		for u in users:
			for i in items:
				if (mat[items.index(i)][users.index(u)] == 1):
					for u2 in users:
						if (mat[items.index(i)][users.index(u2)] == 1):
							if (user2user[users.index(u)][users.index(u2)] == 0):
								user2user[users.index(u)][users.index(u2)] = 1
								#user2user[users.index(u2)][users.index(u)] = 1
								outputf.write("%s" %u + "\t" + "%s" %u2 + "\n")
								#Experimental, writing a square simmetrical matrix 
								#outputf.write("%s" %u2 + "\t" + "%s" %u + "\n")
								print "User2User matrix now has value 1 in row: " + "%s" %users.index(u) + " and column: " + "%s" %users.index(u2)
		
		
		outputf.close()
		# Just some time to finish writing
		time.sleep(60)
		
		# Figure out what the outputfile name is and use it to name
		# the inputfile and the outputfile for fitHRG 
		outputfilename = "%s" %self.outputfile
		fqn_filename = outputfilename.split('.')				
		input_fitHRG = "%s" %fqn_filename[0] + ".pairs"
		os.system("cp %s" %self.outputfile + " %s" %input_fitHRG)
		time.sleep(5)
		os.system("rm %s" %self.outputfile)
		time.sleep(5)
		output_fitHRG = "%s" %fqn_filename[0] + "_best-dendro.hrg"
		output_predictHRG = "%s" %fqn_filename[0] + "-ranked.wpairs"
		
		# Preparing for RFN by substituting spaces for commas
		rfn_followers = open(input_fitHRG, 'r')
		outputfile_ifn2pfn = open(self.outputfile, 'w')

		# Read input_fitHRG and iterate over it to write to outputf2	
		for line in rfn_followers:			
			pat = re.compile(r'\s+')
			line = pat.sub(',', line)
			readline = line.split(',')
			outputfile_ifn2pfn.write("%s" %readline[0] + "," + "%s" %readline[1] + "\n")
		rfn_followers.close()
		outputfile_ifn2pfn.close()
				
		print "Running fitHRG_GPL ... with file %s" %input_fitHRG		
		background = fitHRG(input_fitHRG)
		#background.isDaemon()
		background.start()
		time.sleep(60*3)
		print "Finished running fitHRG_GPL"					
		
		# Only run twice. Check if not then run again.				
		if not(os.path.exists(output_fitHRG)):	
			# Run fitHRG using outputfile containing userXuser matrix				  
			print "Running fitHRG_GPL ... with file %s" %input_fitHRG		
			background = fitHRG(input_fitHRG)
			background.isDaemon()
			background.start()
			time.sleep(60*3)
			print "Finished running fitHRG_GPL"
	
		# Run predictHRG
		print "Running predictHRG_GPL ... with input file %s" %input_fitHRG + " and output file %s" %output_fitHRG
		background_predictHRG = predictHRG(input_fitHRG, output_fitHRG)
		background_predictHRG.start()
		time.sleep(60*30)
		print "Finished running predictHRG_GPL"

		# Only run twice. Check if not then run again.
		if not(os.path.exists(output_predictHRG)):
			print "Predicted pairs doesn't exist yet"
			print "Sleeping for 10 minutes ..."
			time.sleep(60*10)
		
		# Check if the file does exist now. If so run with the predicted followers.
		if (os.path.exists(output_predictHRG)) and (int(os.path.getsize(output_predictHRG)) > 0):

			# Open files for predictHRG
			predicted_followers = open(output_predictHRG, 'r')

			# Read output of predictHRG and iterate over it to write to outputfile2	
			for line in predicted_followers:			
				pat = re.compile(r'\s+')
				line = pat.sub(',', line)
				readline = line.split(',')
				print "looping ... line: %s" %readline[0]

				try:
					# Add all predictions concerning the root user id
					if (int(readline[0]) == int(user_id)) and (float(readline[2]) > 0.0):
						users_p.append(int(readline[1]))	
						outputf2.write("%s" %readline[0] + "," + "%s" %readline[1] + "," + "%s" %readline[2] + "\n")						
						print "Predicted Follower of %s: " %readline[0] + ",%s" %readline[1] + "," + "%s" %readline[2] + "\n"
				except:
					continue
			predicted_followers.close()
			
			# Open files for predictHRG
			predicted_followers = open(output_predictHRG, 'r')
			# Read output of predictHRG (again) and iterate over it to write to outputfile2	(for implicit connections)
			for line in predicted_followers:			
				pat = re.compile(r'\s+')
				line = pat.sub(',', line)
				readline = line.split(',')
				print "looping ... line: %s" %readline[0]
				
				# Add all predictions concerning the implicit connections of the root user id
				try:
					if ((user2user[int(readline[0])][users.index(user_id)]) or (user2user[users.index(user_id)][int(readline[0])])) and (float(readline[2]) > 0.0):
						users_p.append(int(readline[1]))	
						outputf2.write("%s" %user_id + "," + "%s" %readline[1] + "," + "%s" %readline[2] + "\n")						
						print "Predicted Follower of %s: " %readline[0] + ",%s" %readline[1] + "," + "%s" %readline[2] + "\n"
				except:
					continue
			predicted_followers.close()		
			
			implicit_followers = open(input_fitHRG, 'r')

			# Read input_fitHRG and iterate over it to write to outputf2	
			for line in implicit_followers:			
				pat = re.compile(r'\s+')
				line = pat.sub(',', line)
				readline = line.split(',')
				print "looping ... line: %s" %readline[0]

				try:
					# Add all predictions concerning the root user id
					if (int(readline[0]) == int(user_id)) and not(int(readline[1]) == int(user_id)):
						users_p.append(int(readline[1]))	
						outputf2.write("%s" %readline[0] + "," + "%s" %readline[1] + "\n")						
						print "Predicted (implicit) Follower of %s: " %readline[0] + ",%s" %readline[1] + "\n"
				except:
					continue
			implicit_followers.close()

			implicit_followers = open(input_fitHRG, 'r')

			# Read input_fitHRG and iterate over it to write to outputf2	
			for line in implicit_followers:			
				pat = re.compile(r'\s+')
				line = pat.sub(',', line)
				readline = line.split(',')
				print "looping ... line: %s" %readline[0]

				# Add all predictions concerning the implicit connections of the root user id
				try:
					if (user2user[int(readline[0])][users.index(user_id)]) and not(int(readline[1]) == int(user_id)):
						users_p.append(int(readline[1]))	
						outputf2.write("%s" %readline[0] + "," + "%s" %readline[1] + "\n")						
						print "Predicted Follower of %s: " %readline[0] + ",%s" %readline[1] + "\n"
				except:
					continue
			implicit_followers.close()
					
		# And if predictHRG could not run then use the implicit followers
		# because those are our best 'predictions' at this point.
		else:		
			implicit_followers = open(input_fitHRG, 'r')

			# Read input_fitHRG and iterate over it to write to outputf2	
			for line in implicit_followers:			
				pat = re.compile(r'\s+')
				line = pat.sub(',', line)
				readline = line.split(',')
				print "looping ... line: %s" %readline[0]

				try:
					# Add all predictions concerning the root user id
					if (int(readline[0]) == int(user_id)) and not(int(readline[1]) == int(user_id)):
						users_p.append(int(readline[1]))	
						outputf2.write("%s" %readline[0] + "," + "%s" %readline[1] + "\n")						
						print "Predicted (implicit) Follower of %s: " %readline[0] + ",%s" %readline[1] + "\n"
				except:
					continue
			implicit_followers.close()

			implicit_followers = open(input_fitHRG, 'r')

			# Read input_fitHRG and iterate over it to write to outputf2	
			for line in implicit_followers:			
				pat = re.compile(r'\s+')
				line = pat.sub(',', line)
				readline = line.split(',')
				print "looping ... line: %s" %readline[0]

				# Add all predictions concerning the implicit connections of the root user id
				try:
					if (user2user[int(readline[0])][users.index(user_id)]) and not(int(readline[1]) == int(user_id)):
						users_p.append(int(readline[1]))	
						outputf2.write("%s" %readline[0] + "," + "%s" %readline[1] + "\n")						
						print "Predicted Follower of %s: " %readline[0] + ",%s" %readline[1] + "\n"
				except:
					continue
			implicit_followers.close()
			

##############
def RunMain():
	usage = "(First version) usage: %prog <inputfilepath> <outputfilepath> <screen_name>"
	parser = OptionParser(usage)
	(options, args) = parser.parse_args()

	if( len(args) < 3):
		print "Invalid number of arguments. Use ConventionalFollowers.py --help to see the details."
	else:
		inputfilepath = args[0]
		outputfilepath = args[1]
		screen_name = args[2]

		try:
			print "Predicting links between implicit followers to obtain predicted followers"

			ImplicitFollowers2Network(inputfilepath, outputfilepath, screen_name)
		except:
			pass
			raise

if( __name__ == "__main__"):
	RunMain()
